package com.xiaode.validator;

import java.lang.annotation.Annotation;
import java.lang.reflect.Parameter;
import java.util.Collection;
import java.util.Map;
import javax.validation.constraints.Email;
import javax.validation.constraints.Max;
import javax.validation.constraints.Min;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotEmpty;
import javax.validation.constraints.Pattern;
import javax.validation.constraints.Size;
import com.jfinal.aop.Interceptor;
import com.jfinal.aop.Invocation;
import com.jfinal.core.Controller;
import com.jfinal.kit.Kv;
import com.jfinal.kit.Ret;
import com.xiaode.common.anotation.BooleanV;
import com.xiaode.common.anotation.Captcha;
import com.xiaode.common.anotation.JSONArrayString;
import com.xiaode.common.anotation.JSONObjString;
import com.xiaode.util.RegexUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONUtil;

public class ParameterValidator implements Interceptor{

	@Override
	public void intercept(Invocation inv) {
		Parameter[] parameters = inv.getMethod().getParameters();// 获取方法的全部传参
		
        for (int index = 0; index < parameters.length; index++) {// 遍历全部参数
        	Object validObject = inv.getArg(index);// 获取传入参数的值

        	String parameName = parameters[index].getName();// 传入参数的名称
        	Annotation[] as = parameters[index].getAnnotations();// 获取参数上的所有注解
        	
        	for(Annotation a : as) {// 遍历参数上的注解
        		if(a.annotationType() == NotBlank.class) { //单独String类型判空
                    if (validObject == null || (validObject instanceof String && StrUtil.isBlank((String) validObject))) {
                        String msg = parameName + " is blank ";
                        Controller c = inv.getController();
                        Kv kv = Kv.by("msg", msg).set("code", 3000);
                        c.renderJson(Ret.fail().set("error", kv));
                    	return;
                    }
        		}else if(a.annotationType() == NotEmpty.class) {//对象类型判空
        			if (validObject == null || ObjectUtil.isEmpty(validObject)) {
                        String msg = parameName + " is null or empty ";
                        Controller c = inv.getController();
                        Kv kv = Kv.by("msg", msg).set("code", 3000);
                        c.renderJson(Ret.fail().set("error", kv));
                    	return;
                    }
        		}
        		
        		
        		
        		
        		
        		else if(a.annotationType() == BooleanV.class) {
                	if (validObject != null){
                		if(!(validObject instanceof Boolean)) {
	                        String msg = parameName + " is Not Boolean ";
	                        Controller c = inv.getController();
	                        Kv kv = Kv.by("msg", msg).set("code", 3000);
	                        c.renderJson(Ret.fail().set("error", kv));
	                    	return;
	                    }
                	}
        		}else if(a.annotationType() == Max.class) {
        			if (validObject != null){
	        			Max max = (Max)a;
	                	if (max.value() < ((Number) validObject).longValue()) {
	                        String msg = parameName + " max value is " + max.value() + ", but current value is " + validObject;
	                        Controller c = inv.getController();
	                        Kv kv = Kv.by("msg", msg).set("code", 3000);
	                        c.renderJson(Ret.fail().set("error", kv));
	                    	return;
	                    }
        			}
        		}else if(a.annotationType() == Min.class) {
        			if (validObject != null){
	        			Min min = (Min)a;
	                	if (min.value() > ((Number) validObject).longValue()) {
	                        String msg = parameName + " min value is " + min.value() + ", but current value is " + validObject;
	                        Controller c = inv.getController();
	                        Kv kv = Kv.by("msg", msg).set("code", 3000);
	                        c.renderJson(Ret.fail().set("error", kv));
	                    	return;
	                    }
        			}
        		}else if(a.annotationType() == Size.class) {// 大小长度
        			if (validObject != null){
	        			Size size = (Size)a;
        				Integer len = getObjectLen(validObject);
                        if (len < size.min() || len > size.max()) {
                            String msg = parameName + " need size is " + size.min() + " ~ " + size.max() + ", but current value size (or length) is " + len ;
                            Controller c = inv.getController();
                            Kv kv = Kv.by("msg", msg).set("code", 3000);
                            c.renderJson(Ret.fail().set("error", kv));
                        	return;
                        }
        			}
        		}else if(a.annotationType() == Email.class) {
        			if (validObject != null){
	        			Email email = (Email)a;
	        			if (!matches(email, validObject.toString())) {
	                        String msg = parameName + " is not email ";
	                        Controller c = inv.getController();
	                        Kv kv = Kv.by("msg", msg).set("code", 3000);
	                        c.renderJson(Ret.fail().set("error", kv));
	                    	return;
	                    }
        			}
        		}else if(a.annotationType() == Pattern.class) { //带注释的{@code CharSequence}必须与指定的正则表达式匹配。正则表达式遵循Java正则表达式约定
        			if (validObject != null){
	        			Pattern pattern = (Pattern)a;
	        			if (!matches(pattern, validObject.toString())) {
	                        String msg = parameName + " is null or not matches the regex ";
	                        Controller c = inv.getController();
	                        Kv kv = Kv.by("msg", msg).set("code", 3000);
	                        c.renderJson(Ret.fail().set("error", kv));
	                    	return;
	                    }
        			}
        		}else if(a.annotationType() == JSONArrayString.class) { //是否为json数组字符串
        			if (validObject != null){
	        			if (!(validObject instanceof String) || !JSONUtil.isTypeJSONArray((String)validObject)) {
	                        String msg = parameName + " is null or not JSONArrayString ";
	                        Controller c = inv.getController();
	                        Kv kv = Kv.by("msg", msg).set("code", 3000);
	                        c.renderJson(Ret.fail().set("error", kv));
	                    	return;
	                    }
        			}
        		}else if(a.annotationType() == JSONObjString.class) { //是否为json对象
        			if (validObject != null){
	        			if (!(validObject instanceof String) || !JSONUtil.isTypeJSONObject((String)validObject)) {
	                        String msg = parameName + " is null or not JSONObjString ";
	                        Controller c = inv.getController();
	                        Kv kv = Kv.by("msg", msg).set("code", 3000);
	                        c.renderJson(Ret.fail().set("error", kv));
	                    	return;
	                    }
        			}
        		}else if(a.annotationType() == Captcha.class) {//是否是验证码参数
        			Controller c = inv.getController();
        			if ( !c.validateCaptcha("captcha") ) {
        				String msg = "验证码错误!";
                        Kv kv = Kv.by("msg", msg).set("code", 3000);
        				c.renderJson(Ret.fail().set("error", kv));
        	    		return;
        	    	}
        		}
        		
        	}
        }
        inv.invoke();
		
	}

	
	
	
	
	private int getObjectLen(Object validObject) {
        if (validObject instanceof Number) {
            return ((Number) validObject).intValue();
        }
        if (validObject instanceof CharSequence) {
            return ((CharSequence) validObject).length();
        }
        if (validObject instanceof Map) {
            return ((Map<?, ?>) validObject).size();
        }
        if (validObject instanceof Collection) {
            return ((Collection<?>) validObject).size();
        }
        if (validObject.getClass().isArray()) {
            return ((Object[]) validObject).length;
        }
        return 0;
    }

    private static boolean matches(Email email, String value) {
        Pattern.Flag[] flags = email.flags();
        String regexp = ".*".equals(email.regexp()) ? RegexUtil.EMAIL : email.regexp();
        if (flags.length == 0) {
            return value.matches(regexp);
        }
        int intFlag = 0;
        for (Pattern.Flag flag : flags) {
            intFlag = intFlag | flag.getValue();
        }
        java.util.regex.Pattern p = java.util.regex.Pattern.compile(regexp, intFlag);
        return p.matcher(value).matches();
    }
    
    private static boolean matches(Pattern pattern, String value) {
        Pattern.Flag[] flags = pattern.flags();
        if (flags.length == 0) {
            return value.matches(pattern.regexp());
        }
        int intFlag = 0;
        for (Pattern.Flag flag : flags) {
            intFlag = intFlag | flag.getValue();
        }
        java.util.regex.Pattern p = java.util.regex.Pattern.compile(pattern.regexp(), intFlag);
        return p.matcher(value).matches();
    }
    
    
    
    
    
    
    
	
}
